home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / Devices / AsyncDriverSample 1.0b4 / AsyncDriverMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-07  |  6.8 KB  |  211 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        AsyncDriverMain.c
  3.  
  4.     Contains:    Driver glue modified for use with CodeWarrior custom header.
  5.  
  6.     Written by:    Quinn "The Eskimo!"
  7.  
  8.     Copyright:    © 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.     You may incorporate this sample code into your applications without
  13.     restriction, though the sample code has been provided "AS IS" and the
  14.     responsibility for its operation is 100% yours.  However, what you are
  15.     not permitted to do is to redistribute the source as "DSC Sample Code"
  16.     after having made changes. If you're going to re-distribute the source,
  17.     we require that you make it clear in the source that the code was
  18.     descended from Apple Sample Code, but that you've made changes.
  19.  
  20.     Change History (most recent first):
  21.  
  22.          <5>    970307    Quinn        Tidied up CodeWarrior driver header,
  23.                                      as per Chad Magendanz's suggestions.
  24.          <4>    970206    Quinn        Ported to CodeWarrior, which required
  25.                                     syntactic changes everywhere and some
  26.                                     changes to how the entry point offsets
  27.                                     are calculated.  Also added A4 save, setup
  28.                                     and restore.
  29.          <3>    941027    BL°B        Incomplete async routines should return noErr .
  30.          <2>    960803    BL°B        Moved to Universal Headers (post ETO 18).
  31.          <1>     10/94    BL°B        Corrected asynch not-complete return case
  32.                                     to put 0 in D0.
  33.          <0>     10/93    gs and JML    Clean up for Sample Code release.
  34.  
  35. */
  36.  
  37. #include <A4Stuff.h>
  38. #include <Devices.h>
  39. #include <DriverGestalt.h>
  40.  
  41. /* This file is necessary because the standard Metrowerks driver header
  42.     has a number of problems:
  43.         
  44.     o    It assumes that the driver entry point is using C calling
  45.         conventions.  As you can't declare C calling convention routines
  46.         in Pascal, I'm stuck with doing some sort of C glue.  Given
  47.         the other problems, I thought might as well do the whole enchilada.
  48.         
  49.     o It does not handle _KillIO processing.
  50.     
  51.     o It doesn't set ioResult for immediate calls.
  52.         
  53.    This code is based on the "Driver.a" used for the long standing
  54.       DTS RAMDisk sample, modified for operation in the CodeWarrior
  55.       environment.
  56. */
  57.  
  58. // External declarations for the Pascal routines.
  59.  
  60. extern pascal OSErr DRVROpen(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  61. extern pascal OSErr DRVRPrime(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  62. extern pascal OSErr DRVRControl(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  63. extern pascal OSErr DRVRStatus(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  64. extern pascal OSErr DRVRClose(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  65.  
  66. // The Universal headers no longer define simple constants for low-memory
  67. //  globals, so we have to define our own.
  68.  
  69. enum {
  70.     JIODone = 0x8FC
  71. };
  72.  
  73. // Constants for VMImmune bit in dCtlFlags.
  74.  
  75. enum {
  76.     dVMImmuneBit = 0,
  77.     dVMImmuneMask = 0x0001
  78. };
  79.         
  80. /*    If dVMImmuneBit is set to true the VM system does not hold down
  81.     parameter blocks (or the data that read/write parameter blocks point to)
  82.     passed to this driver.
  83. */
  84.  
  85. /*    Driver Header
  86.  
  87.     The code is based on "Driver.a" from the RAMDisk sample.
  88.     Unfortunately I had to make a number of changes.  Some of them are purely
  89.     syntactic, using 0x instead of $ for example, but others are more substantial.
  90.     CodeWarrior's assembler doesn't let you go "dc.b Label1 - Label2", so
  91.     the entry points in the driver header are now calculated using the label
  92.     and a static offset.
  93.  
  94.     My second change was to save, setup and restore A4 in the code.
  95. */
  96.  
  97. asm void __Startup__(void);
  98. asm void __Startup__(void)
  99. {
  100. DHeader:
  101.  
  102. DFlags:            dc.w    dReadEnableMask        \
  103.                         + dWritEnableMask    \
  104.                         + dCtlEnableMask    \
  105.                         + dStatEnableMask    \
  106.                         + dNeedLockMask        \
  107.                         + dVMImmuneMask        \
  108.                         + kmDriverGestaltEnableMask    // <5> Driver flags
  109.  
  110. DDelay:            dc.w    0                            // none
  111. DEMask:            dc.w    0                            // DA event mask
  112. DMenu:            dc.w    0                            // no menu
  113.  
  114.                 dc.w    DOpen + 8                     // <4> <5> offset to Open
  115.                 dc.w    DPrime + 10                     // <4> <5> offset to Prime
  116.                 dc.w    DControl + 12                 // <4> <5> offset to Control
  117.                 dc.w    DStatus + 14                 // <4> <5> offset to Status
  118.                 dc.w    DClose + 16                     // <4> <5> offset to Close
  119.  
  120. Name:            dc.b    "\p.AsyncDriverSample"        // <4> <5> name of driver
  121.                 
  122. DOpen:            pea        DRVROpen
  123.                 bra.s    DRVRDispatch
  124.                                 
  125. DPrime:            pea        DRVRPrime
  126.                 bra.s    DRVRDispatch
  127.                                 
  128. DControl:        pea        DRVRControl
  129.                 bra.s    DRVRDispatch
  130.  
  131. DStatus:        pea        DRVRStatus
  132.                 bra.s    DRVRDispatch
  133.  
  134. DClose:            pea        DRVRClose                    // and fall thru to DRVRDispatch
  135.  
  136. DRVRDispatch:
  137.                 movem.l a0/a1/a4, -(sp)                // <4> save registers (for IODone)
  138.                                 
  139.         // Push parameters for driver routines with Pascal calling conventions.
  140.  
  141.                 clr.w    -(sp)                        // save room for result
  142.                 move.l    a0, -(sp)                    // push paramblock ptr on stack
  143.                 move.l    a1, -(sp)                    // push dce ptr on stack
  144.  
  145.         // Now setup A4 -- have to do this after above because it messes up a0.
  146.         
  147.                 jsr        SetCurrentA4                // <4> establish CodeWarrior globals
  148.         
  149.         // Now call the driver routine.
  150.  
  151.                 movea.l 0x16(sp), a0                // load address of driver routine into a0
  152.                 jsr        (a0)                        // go to it!
  153.                                 
  154.                 move.w    (sp)+, d0                    // put result into d0                                
  155.                 movem.l (sp)+, a0/a1/a4                // <4> restore registers (for IODone)
  156.                 addq.l    #4, a7                        // clear driver routine address off stack
  157.  
  158. // Check for special case exits (Open, Close, KillIO, Immediate, incomplete Async)
  159. // Open, Close and KillIO always RTS to the Device Manager with the driver result
  160. // in 
  161.  
  162.                 move.w    struct(IOParam.ioTrap)(a0), d1    // copy low byte of trap word to d1
  163.  
  164.         // _Open check
  165.                 tst.b        d1                        // _Open == A000
  166.                 beq.s        Done                    // rts if _Open
  167.  
  168.         // _Close check
  169.                 cmpi.b    #1, d1                        // _Close == A001
  170.                 beq.s        Done                    // rts if _Close
  171.  
  172.         // _KillIO check
  173.                 cmpi.b    #6, d1                        // _KillIO == A006
  174.                 beq.s        Done                    // rts if _KillIO
  175.  
  176.         // It must be _Read, _Write, _Control, or _Status
  177.         
  178.         // Immediate check
  179.                 btst        #noQueueBit, d1            // test immediate bit
  180.                 beq.s        NotImmediate            // branch if not immediate
  181.  
  182. Immediate:
  183.                 move.w    d0, struct(IOParam.ioResult)(a0)
  184.                                                     // The Device Manager doesn't set ioResult,
  185.                                                     // so we do just in case the caller checks
  186.                                                     // ioResult instead of the function result.
  187.                 bra.s        Done                    // rts if immediate
  188.                                 
  189. NotImmediate:
  190.  
  191. // <3> BL°B
  192. // If the call is asynchronous and not complete, it should return noErr (0)
  193. // in D0 instead of 1 -- otherwise, the Device Manager sees the 1 and
  194. // returns 1 as an error to the caller. If the File Manager is the caller,
  195. // it converts the 1 to ioErr and returns it to the program that called
  196. // it.     See develop issue 13 page 10.
  197. //
  198.         // Incomplete Async check
  199.                 cmp.w        #1, d0                    // We're using the convention that if the
  200.                                                     // driver result = 1 then the device driver
  201.                                                     // hasn't completed the non-immediate
  202.                                                     // operation.
  203.                 bne.s        Complete
  204.                 moveq        #0, d0                    // clear D0 and...
  205.                 bra.s        Done                    // rts if the operation is incomplete
  206.  
  207. Complete:        move.l    JIODone, -(sp)                // push jIODone onto stack
  208. Done:            rts
  209.  
  210. }
  211.